/* eslint-disable no-use-before-define */
/**
 * 剪切图片
 */
import EXIF from './exif';

const styleText = `
    .img-cut {
        position: fixed;
        top: 0;
        left: 50%;
        height: 100%;
        width: 100%;
        max-width: 500px;
        -webkit-transform: translate(-50%, 0);
        transform: translate(-50%, 0);
        z-index: 10000;
        background: #000;
    }

    .img-cut .img-cut-select-are {
        padding-top: 100%;
        width: 100%;
        position: absolute;
        top: 50%;
        left: 0;
        -webkit-transform: translateY(-50%);
                transform: translateY(-50%);
    }

    .img-cut-select-are-border {
        position: absolute;
        top: 0;
        left: 0;
        height: 100%;
        width: 100%;
        box-sizing: border-box;
        border: 2px solid #fff;
    }

    .img-cut .img-cut-select-are:before, .img-cut .img-cut-select-are:after {
        content: "";
        height: 100%;
        width: 100%;
        display: block;
        position: absolute;
        background: rgba(0, 0, 0, .4);
        left: 0;
        top: 100%;
    }
    .img-cut .img-cut-select-are:after {
        bottom: 100%;
        top: auto;
    }

    .img-cut .img-cut-origin {
        position: absolute;
        left: 0;
        top: 0%;
        width: 100%;
    }

    .img-cut .img-cut-origin img {
        display: block;
        width: 100%;
        height: auto;
    }

    .img-cut .bott {
        position: absolute;
        bottom: 0;
        left: 0;
        width: 100%;
        color: #fff;
    }

    .img-cut .bott>button {
        display: inline-block;
        line-height: 3;
        width: 40%;
        cursor: pointer;
        // border: 1px solid #dfdcd8;
        border: 0;
        color: inherit;
        background: inherit;
        font-size: 16px;
    }
    .img-cut .bott>button:nth-child(2) {
        float: right;
    }

    .img-cut .transition {
        -webkit-transition: all .4s;
        transition: all .4s;
    }
`;
const styleId = 'wpt-cut-img-style';

const DEBUGGER = false;
// 图片最大宽度
const MAX_WIDTH = 1000;
// 图片最大高度
// eslint-disable-next-line no-unused-vars
const MAX_HEIGHT = 2000;
// canvas toBlob polyfill
if (!HTMLCanvasElement.prototype.toBlob) {
    Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
        value(callback, type = 'image/png', quality = 1) {
            const binStr = atob(this.toDataURL(type, quality).split(',')[1]);
            const len = binStr.length;
            const arr = new Uint8Array(len);

            for (let i = 0; i < len; i++) {
                arr[i] = binStr.charCodeAt(i);
            }

            callback(
                new Blob([arr], {
                    type,
                })
            );
        },
    });
}

function consoleFileInfo(file) {
    DEBUGGER && console.log(`大小:${file.size / 1000 / 1000}`);
}

/**
 * [cut 剪切图片,避免跨域]
 * @method cut
 * @param  {String|File}   [imgSrc=''] [图片地址]
 * @param  {Function} callback    [参数: blob]
 * @return {[type]}               [description]
 */
function cut(imgSrc = '', callback) {
    // 如果是file，将其转为url
    let originFile = null;
    if (typeof imgSrc !== 'string') {
        consoleFileInfo(imgSrc);
        originFile = imgSrc;
        imgSrc = URL.createObjectURL(imgSrc);
    }

    // 加载图片
    loadImg(imgSrc, originFile, callback);
}

// 悬着图片有效区域
function selectImg(src, originFile, width, height, naturalWidth, naturalHeight, callback) {
    DEBUGGER && console.log(`图片信息: width:${width}, height:${height}`);
    // style之创建一次即可
    if (!document.querySelector(`#${styleId}`)) {
        const style = document.createElement('style');
        style.id = styleId;
        style.innerText = styleText;
        document.head.appendChild(style);
    }

    // 创建面板
    const $parent = document.createElement('div');
    $parent.className = 'img-cut';
    $parent.innerHTML = `
        <div class="img-cut-origin">
            <img src="${src}" width="${width}" height="${height}" alt="图片加载失败" />
        </div>
        <div class="img-cut-select-are">
            <div class="img-cut-select-are-border"></div>
        </div>
        <div class="bott">
            <button class="cancel">取消</button>
            <button class="submit" disabled>完成</button>
        </div>
    `;
    document.body.appendChild($parent);

    // 选择区
    const $select = $parent.querySelector('.img-cut-select-are-border');
    const $img = $parent.querySelector('.img-cut-origin');

    const parentHeight = $parent.clientHeight;
    const parentWidth = $parent.clientWidth;

    const IMG_SCALE_HEIGHT = (parentWidth / width) * height;
    let currentTop = (parentHeight - IMG_SCALE_HEIGHT) / 2;
    const cacheTop = currentTop;

    // 边界
    const TOP_MAX = (parentHeight - parentWidth) / 2;
    const TOP_MIN = TOP_MAX + parentWidth - IMG_SCALE_HEIGHT;

    let changeY = currentTop;

    // 初始化位置
    setPosition($img, changeY);
    // $img.style.cssText += `transform: translateY(${changeY}px);`

    // 是否可以移动图片
    const isCanMove = width < height;
    let allowUserAction = false;
    // 图片剪切信息
    let cutInfo;

    // 对pc的兼容
    const PC = !navigator.userAgent.toLowerCase().match(/phone|ios|android|ipad|ipod|tablet/g);

    const touchstart = PC ? 'mousedown' : 'touchstart';
    const touchmove = PC ? 'mousemove' : 'touchmove';
    const touchend = PC ? 'mouseup' : 'touchend';

    // 是否触摸开始
    let isStart;

    // 设置位置
    function setPosition($dom, top = 0) {
        if (typeof top === 'number') {
            top += 'px';
        }
        $dom.style.cssText += `-webkit-transform: translateY(${top}); transform: translateY(${top});`;
    }

    // 重置
    function reset() {
        isStart = false;

        // 对currentTop进行边界校验
        if (changeY <= TOP_MAX && changeY >= TOP_MIN) {
            currentTop = changeY;
            setPosition($img, currentTop);
            return;
        }

        if (changeY > TOP_MAX) {
            currentTop = TOP_MAX;
        }
        if (changeY < TOP_MAX) {
            currentTop = TOP_MIN;
        }

        // 添加动画效果
        $img.classList.add('transition');
        // eslint-disable-next-line no-unused-expressions
        $img.clientWidth;
        setPosition($img, currentTop);

        function transitionend() {
            $img.classList.remove('transition');
            $img.removeEventListener('transitionend', transitionend);
            $img.removeEventListener('webkitTransitionend', transitionend);
        }
        $img.addEventListener('transitionend', transitionend);
        $img.addEventListener('webkitTransitionEnd', transitionend);
    }

    // 开启状态
    function open() {
        $parent.querySelector('.submit').disabled = false;
        allowUserAction = true;
    }

    // 关闭状态
    function close() {
        $parent.querySelector('.submit').disabled = true;
        allowUserAction = false;
    }

    // 是否可以移动图片
    if (isCanMove) {
        let y = 0;
        $select.addEventListener(touchstart, event => {
            // do sth
            event.preventDefault();
            y = PC ? event.clientY : event.touches[0].clientY;
            isStart = true;
        });

        $select.addEventListener(touchmove, event => {
            // do sth
            if (!allowUserAction || !isStart) {
                return;
            }
            event.preventDefault();
            const Y = PC ? event.clientY : event.touches[0].clientY;
            const changeTop = currentTop + (Y - y);

            changeY = changeTop;
            setPosition($img, changeY);
        });

        $select.addEventListener(touchend, () => {
            // do sth
            allowUserAction && reset();
        });

        PC
            && $select.addEventListener('mouseleave', () => {
                allowUserAction && reset();
            });
    } else {
        // 缩放后宽度
        const scaleWidth = (parentWidth * width) / height;
        cutInfo = {
            width: parentWidth,
            height: parentWidth,
            x: -(scaleWidth - parentWidth) / 2,
            y: 0,
            originWidth: scaleWidth,
            originHeight: parentWidth,
        };
    }

    // 阻止屏幕滚动
    $parent.addEventListener('touchmove', event => {
        event.stopPropagation();
        event.preventDefault();
    });
    // 取消与确认
    $parent.addEventListener('click', event => {
        const classList = event.target.classList;
        if (classList.contains('cancel')) {
            // 取消事件：移除元素
            document.body.removeChild($parent);
        } else if (classList.contains('submit')) {
            // 确认事件
            const info = isCanMove
                ? {
                    width: parentWidth,
                    height: parentWidth,
                    x: 0,
                    y: -((IMG_SCALE_HEIGHT - parentWidth) / 2 - (currentTop - cacheTop)),
                    originWidth: parentWidth,
                    originHeight: IMG_SCALE_HEIGHT,
                }
                : cutInfo;

            // 关闭用户交互
            close();
            // 获取简介后的图片对象
            const scalePercent = isCanMove ? naturalWidth / parentWidth : naturalHeight / parentWidth;
            DEBUGGER && console.log(naturalWidth / parentWidth, naturalWidth, parentWidth);

            getCutFile(
                $img.querySelector('img'),
                info,
                scalePercent,
                file => {
                    $img.querySelector('img').src = URL.createObjectURL(file);

                    setPosition($img, '-50%');
                    $img.style.cssText += ';top: 50%;';

                    consoleFileInfo(file);
                    callback && callback(file);
                    !DEBUGGER && document.body.removeChild($parent);
                },
                originFile
            );
        }
    });

    open();
}

/**
 * [rotateImg 旋转图片]
 * @method rotateImg
 * @param  {DOM}   img       [description]
 * @param  {Number}   rotateDeg [旋转角度]
 * @param  {Function} callback  [回调函数args(src, width, height)]
 * @return {[type]}             [description]
 */
function rotateImg(img, rotateDeg, callback, originFile) {
    const canvas = document.createElement('canvas');
    let { width, height } = img;
    let widthCache;
    let heightCache;
    // let [width, height] = [naturalWidth, naturalHeight]

    // 如果旋转90、270需要交换宽高
    const isRotate90 = rotateDeg % 180 != 0;
    if (isRotate90) {
        [widthCache, heightCache] = [width, height];
        [width, height] = [height, width];
    }

    canvas.width = width;
    canvas.height = height;

    const ctx = canvas.getContext('2d');

    ctx.save();
    ctx.translate(width / 2, height / 2);
    ctx.rotate((Math.PI / 180) * rotateDeg);

    // 如果旋转90，需要交换起始位置坐标
    isRotate90 ? ctx.translate(-height / 2, -width / 2) : ctx.translate(-width / 2, -height / 2);
    ctx.drawImage(img, 0, 0, widthCache, heightCache);
    ctx.restore();

    // DEBUGGER && console.log(`旋转图片 width:${width}  height:${height}`);
    const quality = getQuality(originFile);

    canvas.toBlob(
        file => {
            selectImg(window.URL.createObjectURL(file), file, width, height, width, height, callback);
        },
        'image/jpeg',
        quality
    );
}

// 获取图片质量
function getQuality(file) {
    // eslint-disable-next-line no-unused-vars
    let quality = 1;
    const MAX = 1;

    const fileSize = file ? file.size / 1000 / 1000 : 0;
    if (file && fileSize > MAX) {
        // 图片最大质量 M
        quality = MAX / fileSize / 2;
    }

    return 1;
}

/**
 * [getCutFile 获取剪切后的file对象]
 * @method getCutFile
 * @param  {DOM}   img      [已经加载完毕的Image对象]
 * @param  {Object}   cutInfo  [剪切信息]
 * @param  {Number}   BILI  [缩放比例]
 * @param  {Function} callback [参数：blob对象]
 * @return {[type]}            [description]
 */
function getCutFile(img, cutInfo, scalePercent = 1, callback, originFile) {
    const {
        width, height, x, y, originWidth, originHeight
    } = cutInfo;

    const canvas = document.createElement('canvas');
    canvas.width = width * scalePercent;
    canvas.height = height * scalePercent;

    /**
     * 在这里没有指定图片的大小
     * 按理说我们可以截取制定大小的图片
     */
    const ctx = canvas.getContext('2d');
    img.width = width * scalePercent;
    ctx.drawImage(img, x * scalePercent, y * scalePercent, originWidth * scalePercent, originHeight * scalePercent);

    const quality = getQuality(originFile);

    canvas.toBlob(
        Bob => {
            DEBUGGER
                && console.log(
                    [scalePercent, originWidth, width, originWidth * scalePercent, Bob.size / 1000 / 1000].join('  ')
                );
            callback && callback(Bob);
        },
        'image/jpeg',
        quality
    );
}

/**
 * [loadImg 加载图片]
 * @method loadImg
 * @param  {String}   [src=''] [description]
 * @param  {Function} callback [description]
 * @return {[type]}            [description]
 */
function loadImg(src = '', originFile, callback) {
    const img = new Image();
    img.onload = function () {
        let { width, height } = img;

        const minWidth = Math.min(width, MAX_WIDTH);
        const minHeight = (minWidth / width) * height;

        [width, height] = [minWidth, minHeight];

        img.width = width;
        img.height = height;

        // 读取图片信息
        try {
            EXIF.getData(img, function () {
                const allMetaData = EXIF.getAllTags(this);
                // console.log('图片信息: ', allMetaData)
                // var allMetaDataSpan = document.getElementById("allMetaDataSpan");
                // let div = document.createElement('div')
                // div.textContent = JSON.stringify(allMetaData, null, "\t");
                // document.body.appendChild(div)

                // 如果图片是角度不正，则旋转图片
                const { Orientation = 1 } = allMetaData;
                if (Orientation != 1) {
                    let deg = 0;
                    switch (Orientation) {
                        case 3:
                            deg = 180;
                            break;
                        case 6:
                            deg = 90;
                            break;
                        case 8:
                            deg = -90;
                            break;
                        default:
                            break;
                    }
                    // 不用去旋转图片
                    if (deg == 0) {
                        selectImg(src, originFile, width, height, width, height, callback);
                    } else {
                        rotateImg(img, deg, callback, originFile);
                    }
                    // 旋转图片
                } else {
                    selectImg(src, originFile, width, height, width, height, callback);
                }
            });
        } catch (e) {
            // do nothing
        }
    };
    img.src = src;
}

WPT.cut = WPT.cut || cut;
